/**
 *
 */
package com.angel.common.keyValue.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;

import com.angel.common.helpers.StringHelper;
import com.angel.common.keyValue.KeyValue;
import com.angel.common.keyValue.KeyValueResult;

/**
 * @author William
 *
 */
public class KeyValueResultImpl implements KeyValueResult {

	private Collection<KeyValue> keyValues;

	public KeyValueResultImpl(){
		super();
		this.setKeyValues(new ArrayList<KeyValue>());
	}
	
	public KeyValueResultImpl(Map<String, String> properties){
		super();
		this.setKeyValues(new ArrayList<KeyValue>());
		for(String key: properties.keySet()){
			this.addKeyValue(key, properties.get(key));
		}
	}

	/* (non-Javadoc)
	 * @see com.angel.common.keyValue.KeyValueResult#addAll(java.util.Collection)
	 */
	public <T extends KeyValue> void addAll(Collection<T> keysValues) {
		this.getKeyValues().addAll(keysValues);
	}

	/* (non-Javadoc)
	 * @see com.angel.common.keyValue.KeyValueResult#addKeyValueResult(com.angel.common.keyValue.KeyValueResult)
	 */
	public void addKeyValueResult(KeyValueResult keyValueResult) {
		Collection<Object> keys = keyValueResult.findAllKeys();
		for(Object key: keys){
			Object value = keyValueResult.getResultFor(key);
			this.addKeyValue(new KeyValueImpl(key, value));
		}
	}

	/* (non-Javadoc)
	 * @see com.angel.common.keyValue.KeyValueResult#containsResultFor(java.lang.Object)
	 */
	public Boolean containsResultFor(Object key) {
		return this.getResultFor(key) != null;
	}

	/* (non-Javadoc)
	 * @see com.angel.common.keyValue.KeyValueResult#findAllKeys()
	 */
	@SuppressWarnings("unchecked")
	public <T extends Object> Collection<T> findAllKeys() {
		Collection<T> keys = new ArrayList<T>();
		for(KeyValue keyValue: keyValues){
			keys.add((T) keyValue.getKey());
		}
		return keys;
	}

	/* (non-Javadoc)
	 * @see com.angel.common.keyValue.KeyValueResult#findAllResults()
	 */
	@SuppressWarnings("unchecked")
	public <T extends Object> Collection<T> findAllResults() {
		Collection<T> keys = new ArrayList<T>();
		for(KeyValue keyValue: keyValues){
			keys.add((T) keyValue.getValue());
		}
		return keys;
	}

	/* (non-Javadoc)
	 * @see com.angel.common.keyValue.KeyValueResult#getResultFor(java.lang.Object)
	 */
	public Object getResultFor(Object key) {
		for(KeyValue keyValue: keyValues){
			if(keyValue.isForKey(key)){
				return keyValue.getValue();
			}
		}
		return null;
	}

	/* (non-Javadoc)
	 * @see com.angel.common.keyValue.KeyValueResult#hasResult()
	 */
	public Boolean hasResult() {
		return this.keyValues.size() > 0;
	}

	/* (non-Javadoc)
	 * @see com.angel.common.keyValue.KeyValueResult#hasResultSize(java.lang.Long)
	 */
	public Boolean hasResultSize(Long resultSize) {
		return this.hasResult() && this.keyValues.size() == resultSize;
	}

	/* (non-Javadoc)
	 * @see com.angel.common.keyValue.KeyValueResult#resultSize()
	 */
	public Long resultSize() {
		return new Long(this.keyValues.size());
	}

	/**
	 * @return the keyValues
	 */
	protected Collection<KeyValue> getKeyValues() {
		return keyValues;
	}

	/**
	 * @param keyValues the keyValues to set
	 */
	protected void setKeyValues(Collection<KeyValue> keyValues) {
		this.keyValues = keyValues;
	}

	public <T extends KeyValue> void addKeyValue(T keyValue) {
		this.keyValues.add(keyValue);
	}

	public <T> void addKeyValue(T key, T value) {
		this.addKeyValue(new KeyValueImpl(key, value));
	}

	public <T> Boolean removeKeyValue(T key) {
		if(this.containsResultFor(key)){
			KeyValue keyValueFound = null;
			for(KeyValue keyValue: keyValues){
				if(keyValue.isForKey(key)){
					break;
				}
			}
			if(keyValueFound != null){
				return keyValues.remove(keyValueFound);
			}
		}
		return Boolean.FALSE;
	}

	public <T extends KeyValue> Boolean removeKeyValue(T key) {
		if(this.containsResultFor(key)){
			boolean found = false;
			for(KeyValue keyValue: keyValues){
				if(keyValue.isForKey(key.getKey())){
					found = true;
					break;
				}
			}
			if(found){
				return keyValues.remove(key);
			}
		}
		return Boolean.FALSE;
	}

	public String toString(){
		return StringHelper.convertToPlainString(this.getKeyValues());
	}
}
